package handlers

import (
	"encoding/json"
	"fmt"
	"io"
	"math/rand"
	"net/http"
	"net/url"
	"os"
	"sort"
	"strconv"
	"strings"
	"time"

	"navigation-service/internal/algorithms"
	"navigation-service/internal/database"
	"navigation-service/internal/models"

	"github.com/gin-gonic/gin"
)

// 全局变量
var navigationData *models.NavigationData

// generateID 生成唯一ID
func generateID() string {
	return fmt.Sprintf("%d%d", time.Now().UnixNano(), rand.Intn(1000))
}

// 加载导航数据
func LoadNavigationData() {
	data, err := os.ReadFile("navigation-data.json")
	if err != nil {
		panic("无法读取导航数据文件: " + err.Error())
	}

	err = json.Unmarshal(data, &navigationData)
	if err != nil {
		panic("解析导航数据失败: " + err.Error())
	}

	fmt.Println("导航数据加载成功")
}

// 首页处理器
func IndexHandler(c *gin.Context) {
	c.HTML(http.StatusOK, "index.html", gin.H{
		"title": "个人导航页面",
	})
}

// 导入页面处理器
func ImportHandler(c *gin.Context) {
	c.HTML(http.StatusOK, "import.html", gin.H{
		"title": "导入浏览器数据",
	})
}

// 测试扩展页面处理器
func TestExtensionHandler(c *gin.Context) {
	c.HTML(http.StatusOK, "test-extension.html", gin.H{
		"title": "浏览器扩展测试",
	})
}

// AI分组页面处理器
func AIGroupingHandler(c *gin.Context) {
	c.HTML(http.StatusOK, "ai-grouping.html", gin.H{
		"title": "AI智能分组",
	})
}

// 统计数据页面处理器
func StatsHandler(c *gin.Context) {
	c.HTML(http.StatusOK, "stats.html", gin.H{
		"title": "浏览统计数据",
	})
}

// 获取完整导航数据
func GetNavigationData(c *gin.Context) {
	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "success",
		Data:    navigationData,
	})
}

// 获取所有分类
func GetCategories(c *gin.Context) {
	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "success",
		Data:    navigationData.Categories,
	})
}

// 根据ID获取分类
func GetCategoryByID(c *gin.Context) {
	id := c.Param("id")

	for _, category := range navigationData.Categories {
		if category.ID == id {
			c.JSON(http.StatusOK, models.APIResponse{
				Code:    200,
				Message: "success",
				Data:    category,
			})
			return
		}
	}

	c.JSON(http.StatusNotFound, models.APIResponse{
		Code:    404,
		Message: "分类未找到",
		Data:    nil,
	})
}

// 搜索项目
func SearchItems(c *gin.Context) {
	query := strings.ToLower(c.Query("q"))
	if query == "" {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "搜索关键词不能为空",
			Data:    nil,
		})
		return
	}

	var results []models.NavigationItem
	for _, category := range navigationData.Categories {
		for _, item := range category.Items {
			if strings.Contains(strings.ToLower(item.Name), query) ||
				strings.Contains(strings.ToLower(item.Description), query) {
				results = append(results, item)
			}
		}
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "success",
		Data:    results,
	})
}

// 添加收藏
func AddFavorite(c *gin.Context) {
	var request struct {
		Name string `json:"name"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "请求参数错误",
			Data:    nil,
		})
		return
	}

	// 检查是否已存在
	for _, fav := range navigationData.Favorites {
		if fav == request.Name {
			c.JSON(http.StatusOK, models.APIResponse{
				Code:    200,
				Message: "已存在收藏",
				Data:    navigationData.Favorites,
			})
			return
		}
	}

	navigationData.Favorites = append(navigationData.Favorites, request.Name)

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "添加收藏成功",
		Data:    navigationData.Favorites,
	})
}

// 移除收藏
func RemoveFavorite(c *gin.Context) {
	name := c.Param("name")

	for i, fav := range navigationData.Favorites {
		if fav == name {
			navigationData.Favorites = append(navigationData.Favorites[:i], navigationData.Favorites[i+1:]...)
			c.JSON(http.StatusOK, models.APIResponse{
				Code:    200,
				Message: "移除收藏成功",
				Data:    navigationData.Favorites,
			})
			return
		}
	}

	c.JSON(http.StatusNotFound, models.APIResponse{
		Code:    404,
		Message: "收藏未找到",
		Data:    nil,
	})
}

// 获取收藏列表
func GetFavorites(c *gin.Context) {
	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "success",
		Data:    navigationData.Favorites,
	})
}

// 添加最近使用
func AddRecentlyUsed(c *gin.Context) {
	var request struct {
		Name string `json:"name"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "请求参数错误",
			Data:    nil,
		})
		return
	}

	// 移除已存在的记录
	for i, recent := range navigationData.RecentlyUsed {
		if recent == request.Name {
			navigationData.RecentlyUsed = append(navigationData.RecentlyUsed[:i], navigationData.RecentlyUsed[i+1:]...)
			break
		}
	}

	// 添加到开头
	navigationData.RecentlyUsed = append([]string{request.Name}, navigationData.RecentlyUsed...)

	// 限制最近使用记录数量
	if len(navigationData.RecentlyUsed) > 10 {
		navigationData.RecentlyUsed = navigationData.RecentlyUsed[:10]
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "添加最近使用成功",
		Data:    navigationData.RecentlyUsed,
	})
}

// 获取统计信息
func GetStats(c *gin.Context) {
	totalItems := 0
	for _, category := range navigationData.Categories {
		totalItems += len(category.Items)
	}

	stats := map[string]interface{}{
		"totalItems":        totalItems,
		"totalCategories":   len(navigationData.Categories),
		"favoriteCount":     len(navigationData.Favorites),
		"recentlyUsedCount": len(navigationData.RecentlyUsed),
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "success",
		Data:    stats,
	})
}

// 添加浏览历史记录
func AddBrowsingHistory(c *gin.Context) {
	var requestData struct {
		Visits []models.BrowsingHistory `json:"visits"`
	}

	if err := c.ShouldBindJSON(&requestData); err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "请求参数错误: " + err.Error(),
			Data:    nil,
		})
		return
	}

	err := database.AddBrowsingHistoryToDB(requestData.Visits)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: fmt.Sprintf("成功添加 %d 条浏览记录", len(requestData.Visits)),
		Data:    nil,
	})
}

// 获取浏览历史统计
func GetBrowsingStats(c *gin.Context) {
	stats, err := database.GetBrowsingStatsFromDB()
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "success",
		Data:    stats,
	})
}

// 获取浏览记录
func GetBrowsingRecords(c *gin.Context) {
	records, err := database.GetBrowsingRecordsFromDB()
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "success",
		Data:    records,
	})
}

// 导入书签
func ImportBookmarks(c *gin.Context) {
	// 首先尝试从表单文件中读取
	file, err := c.FormFile("file")
	if err == nil {
		// 从文件中读取数据
		f, err := file.Open()
		if err != nil {
			c.JSON(http.StatusBadRequest, models.APIResponse{
				Code:    400,
				Message: "无法打开文件: " + err.Error(),
				Data:    nil,
			})
			return
		}
		defer f.Close()

		// 读取文件内容
		content, err := io.ReadAll(f)
		if err != nil {
			c.JSON(http.StatusBadRequest, models.APIResponse{
				Code:    400,
				Message: "无法读取文件: " + err.Error(),
				Data:    nil,
			})
			return
		}

		// 解析JSON数据（直接数组格式）
		var bookmarkData []models.Bookmark
		if err := json.Unmarshal(content, &bookmarkData); err != nil {
			c.JSON(http.StatusBadRequest, models.APIResponse{
				Code:    400,
				Message: "JSON解析失败: " + err.Error(),
				Data:    nil,
			})
			return
		}

		err = database.AddBookmarksToDB(bookmarkData)
		if err != nil {
			c.JSON(http.StatusInternalServerError, models.APIResponse{
				Code:    500,
				Message: err.Error(),
				Data:    nil,
			})
			return
		}

		c.JSON(http.StatusOK, models.APIResponse{
			Code:    200,
			Message: fmt.Sprintf("成功从文件导入 %d 个书签", len(bookmarkData)),
			Data:    nil,
		})
		return
	}

	// 如果没有文件，则尝试从JSON请求体中读取（直接数组格式）
	var bookmarkData []models.Bookmark

	if err := c.ShouldBindJSON(&bookmarkData); err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "请求参数错误: " + err.Error(),
			Data:    nil,
		})
		return
	}

	err = database.AddBookmarksToDB(bookmarkData)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: fmt.Sprintf("成功导入 %d 个书签", len(bookmarkData)),
		Data:    nil,
	})
}

// 获取书签列表
func GetBookmarks(c *gin.Context) {
	bookmarks, err := database.GetBookmarksFromDB()
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "success",
		Data:    bookmarks,
	})
}

// 手动导入浏览历史
func ImportBrowsingHistory(c *gin.Context) {
	// 首先尝试从表单文件中读取
	file, err := c.FormFile("file")
	if err == nil {
		// 从文件中读取数据
		f, err := file.Open()
		if err != nil {
			c.JSON(http.StatusBadRequest, models.APIResponse{
				Code:    400,
				Message: "无法打开文件: " + err.Error(),
				Data:    nil,
			})
			return
		}
		defer f.Close()

		// 读取文件内容
		content, err := io.ReadAll(f)
		if err != nil {
			c.JSON(http.StatusBadRequest, models.APIResponse{
				Code:    400,
				Message: "无法读取文件: " + err.Error(),
				Data:    nil,
			})
			return
		}

		// 解析JSON数据（直接数组格式）
		var historyData []models.BrowsingHistory
		if err := json.Unmarshal(content, &historyData); err != nil {
			c.JSON(http.StatusBadRequest, models.APIResponse{
				Code:    400,
				Message: "JSON解析失败: " + err.Error(),
				Data:    nil,
			})
			return
		}

		err = database.AddBrowsingHistoryToDB(historyData)
		if err != nil {
			c.JSON(http.StatusInternalServerError, models.APIResponse{
				Code:    500,
				Message: err.Error(),
				Data:    nil,
			})
			return
		}

		c.JSON(http.StatusOK, models.APIResponse{
			Code:    200,
			Message: fmt.Sprintf("成功从文件导入 %d 条浏览历史记录", len(historyData)),
			Data:    nil,
		})
		return
	}

	// 如果没有文件，则尝试从JSON请求体中读取（直接数组格式）
	var historyData []models.BrowsingHistory

	if err := c.ShouldBindJSON(&historyData); err != nil {
		// 如果直接绑定失败，尝试绑定到带history键的对象
		var requestData struct {
			History []models.BrowsingHistory `json:"history"`
		}

		if err2 := c.ShouldBindJSON(&requestData); err2 != nil {
			c.JSON(http.StatusBadRequest, models.APIResponse{
				Code:    400,
				Message: "请求参数错误: " + err.Error() + " 或 " + err2.Error(),
				Data:    nil,
			})
			return
		}

		historyData = requestData.History
	}

	err = database.AddBrowsingHistoryToDB(historyData)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: fmt.Sprintf("成功导入 %d 条浏览历史记录", len(historyData)),
		Data:    nil,
	})
}

// ==================== AI分组相关API处理器 ====================

// CreateAIGroupingVersion 创建AI分组版本
func CreateAIGroupingVersion(c *gin.Context) {
	var request struct {
		Name        string                  `json:"name" binding:"required"`
		Description string                  `json:"description"`
		Config      models.AIGroupingConfig `json:"config" binding:"required"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "请求参数错误: " + err.Error(),
			Data:    nil,
		})
		return
	}

	version := &models.AIGroupingVersion{
		ID:          generateID(),
		Name:        request.Name,
		Description: request.Description,
		Status:      "pending",
		CreatedAt:   time.Now(),
		UpdatedAt:   time.Now(),
		Config:      request.Config,
		TotalURLs:   0,
		GroupedURLs: 0,
	}

	err := database.CreateAIGroupingVersion(version)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "创建AI分组版本成功",
		Data:    version,
	})
}

// GetAIGroupingVersions 获取所有AI分组版本
func GetAIGroupingVersions(c *gin.Context) {
	versions, err := database.GetAllAIGroupingVersions()
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "success",
		Data:    versions,
	})
}

// ClearAIGroups 清空指定版本的所有分组
func ClearAIGroups(c *gin.Context) {
	versionID := c.Param("id")
	if versionID == "" {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "版本ID不能为空",
			Data:    nil,
		})
		return
	}

	// 检查版本是否存在
	version, err := database.GetAIGroupingVersion(versionID)
	if err != nil {
		c.JSON(http.StatusNotFound, models.APIResponse{
			Code:    404,
			Message: "分组版本不存在",
			Data:    nil,
		})
		return
	}

	// 清空分组
	err = database.ClearAIGroupsByVersionID(versionID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: fmt.Sprintf("清空分组失败: %v", err),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: fmt.Sprintf("成功清空版本 '%s' 的所有分组", version.Name),
		Data:    nil,
	})
}

// ClearAllAIGroups 清空所有分组信息数据
func ClearAllAIGroups(c *gin.Context) {
	// 清空所有分组
	err := database.ClearAllAIGroups()
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: fmt.Sprintf("清空所有分组失败: %v", err),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "成功清空所有分组信息数据",
		Data:    nil,
	})
}

// DeleteAllAIGroupsAndData 删除所有分组版本、分组和URL分配数据
func DeleteAllAIGroupsAndData(c *gin.Context) {
	// 删除所有分组和数据
	err := database.DeleteAllAIGroupsAndData()
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: fmt.Sprintf("删除所有分组和数据失败: %v", err),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "成功删除所有分组版本、分组和URL分配数据",
		Data:    nil,
	})
}

// GetAIGroupingVersion 获取单个AI分组版本
func GetAIGroupingVersion(c *gin.Context) {
	id := c.Param("id")
	if id == "" {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "版本ID不能为空",
			Data:    nil,
		})
		return
	}

	version, err := database.GetAIGroupingVersion(id)
	if err != nil {
		c.JSON(http.StatusNotFound, models.APIResponse{
			Code:    404,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "success",
		Data:    version,
	})
}

// UpdateAIGroupingVersion 更新AI分组版本
func UpdateAIGroupingVersion(c *gin.Context) {
	idStr := c.Param("id")

	var request struct {
		Name        string                  `json:"name"`
		Description string                  `json:"description"`
		Status      string                  `json:"status"`
		Config      models.AIGroupingConfig `json:"config"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "请求参数错误: " + err.Error(),
			Data:    nil,
		})
		return
	}

	// 获取现有版本
	version, err := database.GetAIGroupingVersion(idStr)
	if err != nil {
		c.JSON(http.StatusNotFound, models.APIResponse{
			Code:    404,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	// 更新字段
	if request.Name != "" {
		version.Name = request.Name
	}
	if request.Description != "" {
		version.Description = request.Description
	}
	if request.Status != "" {
		version.Status = request.Status
	}
	if request.Config.AlgorithmType != "" {
		version.Config = request.Config
	}

	err = database.UpdateAIGroupingVersion(version)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "更新AI分组版本成功",
		Data:    version,
	})
}

// DeleteAIGroupingVersion 删除AI分组版本
func DeleteAIGroupingVersion(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "无效的版本ID",
			Data:    nil,
		})
		return
	}

	err = database.DeleteAIGroupingVersion(id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "删除AI分组版本成功",
		Data:    nil,
	})
}

// CreateAIGroup 创建AI分组
func CreateAIGroup(c *gin.Context) {
	var request struct {
		VersionID   int    `json:"versionId" binding:"required"`
		Name        string `json:"name" binding:"required"`
		Description string `json:"description"`
		Color       string `json:"color"`
		Icon        string `json:"icon"`
		Order       int    `json:"order"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "请求参数错误: " + err.Error(),
			Data:    nil,
		})
		return
	}

	group := &models.AIGroup{
		VersionID:   strconv.Itoa(request.VersionID),
		Name:        request.Name,
		Description: request.Description,
		Color:       request.Color,
		Icon:        request.Icon,
		Order:       request.Order,
		URLCount:    0,
	}

	err := database.CreateAIGroup(group)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "创建AI分组成功",
		Data:    group,
	})
}

// GetAIGroups 获取AI分组列表
func GetAIGroups(c *gin.Context) {
	versionIDStr := c.Query("versionId")
	if versionIDStr == "" {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "缺少versionId参数",
			Data:    nil,
		})
		return
	}

	versionID, err := strconv.Atoi(versionIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "无效的版本ID",
			Data:    nil,
		})
		return
	}

	groups, err := database.GetAIGroupsByVersionID(versionID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	// 为每个分组计算实际的URL数量
	for i := range groups {
		groupID, err := strconv.Atoi(groups[i].ID)
		if err != nil {
			fmt.Printf("转换分组ID失败: %s, 错误: %v\n", groups[i].ID, err)
			continue
		}

		assignments, err := database.GetURLGroupAssignmentsByGroupID(groupID)
		if err != nil {
			fmt.Printf("获取分组 %d 的分配记录失败: %v\n", groupID, err)
			// 如果获取分配记录失败，保持原有的urlCount
			continue
		}

		// 更新URL数量
		groups[i].URLCount = len(assignments)
		fmt.Printf("分组 %d (%s) 的URL数量: %d\n", groupID, groups[i].Name, len(assignments))
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "success",
		Data:    groups,
	})
}

// UpdateAIGroup 更新AI分组
func UpdateAIGroup(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "无效的分组ID",
			Data:    nil,
		})
		return
	}

	var request struct {
		Name        string `json:"name"`
		Description string `json:"description"`
		Color       string `json:"color"`
		Icon        string `json:"icon"`
		Order       int    `json:"order"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "请求参数错误: " + err.Error(),
			Data:    nil,
		})
		return
	}

	// 获取现有分组
	groups, err := database.GetAIGroupsByVersionID(0) // 这里需要先实现根据ID获取单个分组的函数
	if err != nil {
		c.JSON(http.StatusNotFound, models.APIResponse{
			Code:    404,
			Message: "分组未找到",
			Data:    nil,
		})
		return
	}

	// 查找指定ID的分组
	var group *models.AIGroup
	for _, g := range groups {
		if g.ID == strconv.Itoa(id) {
			group = &g
			break
		}
	}

	if group == nil {
		c.JSON(http.StatusNotFound, models.APIResponse{
			Code:    404,
			Message: "分组未找到",
			Data:    nil,
		})
		return
	}

	// 更新字段
	if request.Name != "" {
		group.Name = request.Name
	}
	if request.Description != "" {
		group.Description = request.Description
	}
	if request.Color != "" {
		group.Color = request.Color
	}
	if request.Icon != "" {
		group.Icon = request.Icon
	}
	if request.Order != 0 {
		group.Order = request.Order
	}

	err = database.UpdateAIGroup(group)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "更新AI分组成功",
		Data:    group,
	})
}

// DeleteAIGroup 删除AI分组
func DeleteAIGroup(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "无效的分组ID",
			Data:    nil,
		})
		return
	}

	err = database.DeleteAIGroup(id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "删除AI分组成功",
		Data:    nil,
	})
}

// CreateURLGroupAssignment 创建URL分组分配
func CreateURLGroupAssignment(c *gin.Context) {
	var request struct {
		VersionID  int    `json:"versionId" binding:"required"`
		GroupID    int    `json:"groupId" binding:"required"`
		URL        string `json:"url" binding:"required"`
		Title      string `json:"title"`
		Domain     string `json:"domain"`
		Path       string `json:"path"`
		VisitCount int    `json:"visitCount"`
		LastVisit  string `json:"lastVisit"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "请求参数错误: " + err.Error(),
			Data:    nil,
		})
		return
	}

	// 解析时间
	var lastVisit time.Time
	var err error
	if request.LastVisit != "" {
		lastVisit, err = time.Parse("2006-01-02T15:04:05Z", request.LastVisit)
		if err != nil {
			lastVisit, err = time.Parse("2006-01-02 15:04:05", request.LastVisit)
			if err != nil {
				lastVisit = time.Now()
			}
		}
	} else {
		lastVisit = time.Now()
	}

	assignment := &models.URLGroupAssignment{
		VersionID:  fmt.Sprintf("%d", request.VersionID),
		GroupID:    fmt.Sprintf("%d", request.GroupID),
		URL:        request.URL,
		Title:      request.Title,
		Domain:     request.Domain,
		Path:       request.Path,
		VisitCount: request.VisitCount,
		LastVisit:  lastVisit,
	}

	err = database.CreateURLGroupAssignment(assignment)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "创建URL分组分配成功",
		Data:    assignment,
	})
}

// GetURLGroupAssignments 获取URL分组分配
func GetURLGroupAssignments(c *gin.Context) {
	versionIDStr := c.Query("versionId")
	groupIDStr := c.Query("groupId")

	if versionIDStr == "" && groupIDStr == "" {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "缺少versionId或groupId参数",
			Data:    nil,
		})
		return
	}

	var assignments []models.URLGroupAssignment
	var err error

	if versionIDStr != "" {
		versionID, parseErr := strconv.Atoi(versionIDStr)
		if parseErr != nil {
			c.JSON(http.StatusBadRequest, models.APIResponse{
				Code:    400,
				Message: "无效的版本ID",
				Data:    nil,
			})
			return
		}
		assignments, err = database.GetURLGroupAssignmentsByVersionID(versionID)
	} else if groupIDStr != "" {
		groupID, parseErr := strconv.Atoi(groupIDStr)
		if parseErr != nil {
			c.JSON(http.StatusBadRequest, models.APIResponse{
				Code:    400,
				Message: "无效的分组ID",
				Data:    nil,
			})
			return
		}
		assignments, err = database.GetURLGroupAssignmentsByGroupID(groupID)
	}

	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "success",
		Data:    assignments,
	})
}

// UpdateURLGroupAssignment 更新URL分组分配
func UpdateURLGroupAssignment(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "无效的分配ID",
			Data:    nil,
		})
		return
	}

	var request struct {
		GroupID    int    `json:"groupId" binding:"required"`
		Title      string `json:"title"`
		Domain     string `json:"domain"`
		Path       string `json:"path"`
		VisitCount int    `json:"visitCount"`
		LastVisit  string `json:"lastVisit"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "请求参数错误: " + err.Error(),
			Data:    nil,
		})
		return
	}

	// 解析时间
	var lastVisit time.Time
	if request.LastVisit != "" {
		lastVisit, err = time.Parse("2006-01-02T15:04:05Z", request.LastVisit)
		if err != nil {
			lastVisit, err = time.Parse("2006-01-02 15:04:05", request.LastVisit)
			if err != nil {
				lastVisit = time.Now()
			}
		}
	} else {
		lastVisit = time.Now()
	}

	assignment := &models.URLGroupAssignment{
		ID:         strconv.Itoa(id),
		GroupID:    strconv.Itoa(request.GroupID),
		Title:      request.Title,
		Domain:     request.Domain,
		Path:       request.Path,
		VisitCount: request.VisitCount,
		LastVisit:  lastVisit,
	}

	err = database.UpdateURLGroupAssignment(assignment)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "更新URL分组分配成功",
		Data:    assignment,
	})
}

// DeleteURLGroupAssignment 删除URL分组分配
func DeleteURLGroupAssignment(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "无效的分配ID",
			Data:    nil,
		})
		return
	}

	err = database.DeleteURLGroupAssignment(id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "删除URL分组分配成功",
		Data:    nil,
	})
}

// CreateAIGroupingTask 创建AI分组任务
func CreateAIGroupingTask(c *gin.Context) {
	var request struct {
		VersionID int    `json:"versionId" binding:"required"`
		Status    string `json:"status"`
		Progress  int    `json:"progress"`
		Message   string `json:"message"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "请求参数错误: " + err.Error(),
			Data:    nil,
		})
		return
	}

	// 设置默认值
	if request.Status == "" {
		request.Status = "pending"
	}

	task := &models.AIGroupingTask{
		VersionID: fmt.Sprintf("%d", request.VersionID),
		Status:    request.Status,
		Progress:  request.Progress,
		Message:   request.Message,
		StartedAt: time.Now(),
	}

	err := database.CreateAIGroupingTask(task)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "创建AI分组任务成功",
		Data:    task,
	})
}

// GetAIGroupingTask 获取AI分组任务状态
func GetAIGroupingTask(c *gin.Context) {
	versionIDStr := c.Param("versionId")
	versionID, err := strconv.Atoi(versionIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "无效的版本ID",
			Data:    nil,
		})
		return
	}

	task, err := database.GetAIGroupingTaskByVersionID(versionID)
	if err != nil {
		c.JSON(http.StatusNotFound, models.APIResponse{
			Code:    404,
			Message: err.Error(),
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "success",
		Data:    task,
	})
}

// AnalyzeBrowsingPatterns 分析浏览模式
func AnalyzeBrowsingPatterns(c *gin.Context) {
	// 获取浏览历史记录
	records, err := database.GetBrowsingRecordsFromDB()
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: "获取浏览记录失败: " + err.Error(),
			Data:    nil,
		})
		return
	}

	// 分析浏览模式
	analysis := analyzeBrowsingData(records)

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "分析完成",
		Data:    analysis,
	})
}

// TestGroupingAlgorithm 测试分组算法
func TestGroupingAlgorithm(c *gin.Context) {
	var request struct {
		AlgorithmType string `json:"algorithmType" binding:"required"`
		SampleSize    int    `json:"sampleSize"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "请求参数错误: " + err.Error(),
			Data:    nil,
		})
		return
	}

	// 设置默认样本大小
	if request.SampleSize <= 0 {
		request.SampleSize = 50
	}

	// 获取浏览记录作为测试数据
	records, err := database.GetBrowsingRecordsFromDB()
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: "获取浏览记录失败: " + err.Error(),
			Data:    nil,
		})
		return
	}

	// 限制样本大小
	if len(records) > request.SampleSize {
		records = records[:request.SampleSize]
	}

	// 执行算法测试
	result := testGroupingAlgorithm(request.AlgorithmType, records)

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "算法测试完成",
		Data:    result,
	})
}

// analyzeBrowsingData 分析浏览数据
func analyzeBrowsingData(records []models.BrowsingRecord) map[string]interface{} {
	// 统计兴趣领域
	domains := make(map[string]int)
	keywords := make(map[string]int)

	for _, record := range records {
		domains[record.Domain]++
		// 简单的关键词提取（基于域名）
		parts := strings.Split(record.Domain, ".")
		if len(parts) > 1 {
			keywords[parts[0]]++
		}
	}

	// 找出最常访问的域名
	var topDomains []string
	for domain, count := range domains {
		if count > 1 {
			topDomains = append(topDomains, domain)
		}
	}

	// 按访问次数排序
	sort.Slice(topDomains, func(i, j int) bool {
		return domains[topDomains[i]] > domains[topDomains[j]]
	})

	// 限制前5个
	if len(topDomains) > 5 {
		topDomains = topDomains[:5]
	}

	// 分析时间偏好
	timePreferences := analyzeTimePatterns(records)

	// 分析使用习惯
	usageHabits := map[string]interface{}{
		"mostVisitedDomains": topDomains,
		"averageSessionTime": "15分钟", // 这里可以基于实际数据计算
		"totalSites":         len(records),
	}

	// 推断兴趣领域
	interests := inferInterests(topDomains)

	return map[string]interface{}{
		"interests":       interests,
		"timePreferences": timePreferences,
		"usageHabits":     usageHabits,
		"totalRecords":    len(records),
		"uniqueDomains":   len(domains),
	}
}

// analyzeTimePatterns 分析时间模式
func analyzeTimePatterns(records []models.BrowsingRecord) map[string]interface{} {
	// 这里可以实现更复杂的时间模式分析
	// 目前返回模拟数据
	return map[string]interface{}{
		"peakHours":     []string{"09:00-11:00", "14:00-16:00", "20:00-22:00"},
		"weekendUsage":  "较高",
		"weekdayUsage":  "中等",
		"mostActiveDay": "工作日",
	}
}

// inferInterests 推断兴趣领域
func inferInterests(domains []string) []string {
	interestMap := map[string]string{
		"github":        "技术开发",
		"stackoverflow": "技术开发",
		"youtube":       "娱乐休闲",
		"bilibili":      "娱乐休闲",
		"zhihu":         "学习资源",
		"coursera":      "学习资源",
		"udemy":         "学习资源",
		"medium":        "学习资源",
		"reddit":        "社交娱乐",
		"twitter":       "社交娱乐",
		"facebook":      "社交娱乐",
		"linkedin":      "职业发展",
		"indeed":        "职业发展",
		"amazon":        "购物消费",
		"taobao":        "购物消费",
		"jd":            "购物消费",
	}

	interests := make(map[string]bool)
	for _, domain := range domains {
		for keyword, interest := range interestMap {
			if strings.Contains(domain, keyword) {
				interests[interest] = true
			}
		}
	}

	var result []string
	for interest := range interests {
		result = append(result, interest)
	}

	if len(result) == 0 {
		result = []string{"综合浏览"}
	}

	return result
}

// testGroupingAlgorithm 测试分组算法
func testGroupingAlgorithm(algorithmType string, records []models.BrowsingRecord) map[string]interface{} {
	if len(records) == 0 {
		return map[string]interface{}{
			"algorithmType": algorithmType,
			"statistics": map[string]interface{}{
				"totalURLs":      0,
				"groupedURLs":    0,
				"unassignedURLs": 0,
				"groupCount":     0,
				"avgConfidence":  0.0,
				"processingTime": 0,
			},
			"groups":   []map[string]interface{}{},
			"testTime": time.Now().Format("2006-01-02 15:04:05"),
		}
	}

	// 基于真实数据生成分组
	groups := generateGroupsFromRealData(records, algorithmType)

	// 计算统计信息
	totalURLs := len(records)
	groupedURLs := 0
	for _, group := range groups {
		if urlCount, ok := group["urlCount"].(int); ok {
			groupedURLs += urlCount
		}
	}
	unassignedURLs := totalURLs - groupedURLs

	// 计算平均置信度
	avgConfidence := 0.0
	if len(groups) > 0 {
		totalConfidence := 0.0
		for _, group := range groups {
			if confidence, ok := group["confidence"].(float64); ok {
				totalConfidence += confidence
			}
		}
		avgConfidence = totalConfidence / float64(len(groups))
	}

	statistics := map[string]interface{}{
		"totalURLs":      totalURLs,
		"groupedURLs":    groupedURLs,
		"unassignedURLs": unassignedURLs,
		"groupCount":     len(groups),
		"avgConfidence":  avgConfidence,
		"processingTime": 1200, // 毫秒
	}

	return map[string]interface{}{
		"algorithmType": algorithmType,
		"statistics":    statistics,
		"groups":        groups,
		"testTime":      time.Now().Format("2006-01-02 15:04:05"),
	}
}

// generateGroupsFromRealData 基于真实数据生成分组
func generateGroupsFromRealData(records []models.BrowsingRecord, algorithmType string) []map[string]interface{} {
	// 对URL进行去重处理
	deduplicatedRecords := deduplicateURLs(records)

	// 按域名分类URL
	domainGroups := make(map[string][]models.BrowsingRecord)
	for _, record := range deduplicatedRecords {
		domain := record.Domain
		if domain == "" {
			domain = "其他"
		}
		domainGroups[domain] = append(domainGroups[domain], record)
	}

	// 定义分类规则
	categoryRules := map[string]map[string]interface{}{
		"github.com": {
			"name":        "技术开发",
			"description": "代码托管和开发工具",
			"icon":        "💻",
			"color":       "#24292e",
		},
		"stackoverflow.com": {
			"name":        "技术开发",
			"description": "编程问答社区",
			"icon":        "💻",
			"color":       "#f48024",
		},
		"npmjs.com": {
			"name":        "技术开发",
			"description": "包管理器",
			"icon":        "💻",
			"color":       "#cb0000",
		},
		"kubernetes.io": {
			"name":        "技术开发",
			"description": "容器编排平台",
			"icon":        "💻",
			"color":       "#326ce5",
		},
		"docs.docker.com": {
			"name":        "技术开发",
			"description": "容器技术文档",
			"icon":        "💻",
			"color":       "#2496ed",
		},
		"news.ycombinator.com": {
			"name":        "技术开发",
			"description": "技术新闻社区",
			"icon":        "💻",
			"color":       "#ff6600",
		},
		"baidu.com": {
			"name":        "搜索引擎",
			"description": "搜索和导航工具",
			"icon":        "🔍",
			"color":       "#2932e1",
		},
		"hao123.com": {
			"name":        "搜索引擎",
			"description": "网址导航",
			"icon":        "🔍",
			"color":       "#2932e1",
		},
		"weibo.com": {
			"name":        "社交平台",
			"description": "社交媒体和社交网络",
			"icon":        "👥",
			"color":       "#e6162d",
		},
		"twitter.com": {
			"name":        "社交平台",
			"description": "社交媒体平台",
			"icon":        "👥",
			"color":       "#1da1f2",
		},
		"facebook.com": {
			"name":        "社交平台",
			"description": "社交网络",
			"icon":        "👥",
			"color":       "#1877f2",
		},
		"instagram.com": {
			"name":        "社交平台",
			"description": "图片社交平台",
			"icon":        "👥",
			"color":       "#e4405f",
		},
		"reddit.com": {
			"name":        "社交平台",
			"description": "社区论坛",
			"icon":        "👥",
			"color":       "#ff4500",
		},
		"127.0.0.1": {
			"name":        "本地开发",
			"description": "本地开发环境",
			"icon":        "🔧",
			"color":       "#28a745",
		},
		"localhost": {
			"name":        "本地开发",
			"description": "本地开发环境",
			"icon":        "🔧",
			"color":       "#28a745",
		},
		"publicservices.hrss.tj.gov.cn": {
			"name":        "政府服务",
			"description": "政府公共服务网站",
			"icon":        "🏛️",
			"color":       "#0052cc",
		},
		"taobao.com": {
			"name":        "购物消费",
			"description": "电商购物平台",
			"icon":        "🛒",
			"color":       "#ff6900",
		},
		"jd.com": {
			"name":        "购物消费",
			"description": "电商购物平台",
			"icon":        "🛒",
			"color":       "#e1251b",
		},
		"amazon.com": {
			"name":        "购物消费",
			"description": "电商购物平台",
			"icon":        "🛒",
			"color":       "#ff9900",
		},
		"ctrip.com": {
			"name":        "生活服务",
			"description": "旅游出行服务",
			"icon":        "✈️",
			"color":       "#00a651",
		},
		"sohu.com": {
			"name":        "新闻资讯",
			"description": "新闻门户网站",
			"icon":        "📰",
			"color":       "#ff6600",
		},
		"sina.com.cn": {
			"name":        "新闻资讯",
			"description": "新闻门户网站",
			"icon":        "📰",
			"color":       "#e6162d",
		},
		"qq.com": {
			"name":        "新闻资讯",
			"description": "综合门户网站",
			"icon":        "📰",
			"color":       "#12b7f5",
		},
		"163.com": {
			"name":        "新闻资讯",
			"description": "新闻门户网站",
			"icon":        "📰",
			"color":       "#d20000",
		},
		"cnn.com": {
			"name":        "新闻资讯",
			"description": "国际新闻",
			"icon":        "📰",
			"color":       "#cc0000",
		},
		"bbc.com": {
			"name":        "新闻资讯",
			"description": "国际新闻",
			"icon":        "📰",
			"color":       "#bb0000",
		},
	}

	// 按分类聚合域名
	categoryMap := make(map[string][]string)
	for domain := range domainGroups {
		category := "其他"
		for ruleDomain, rule := range categoryRules {
			if strings.Contains(domain, ruleDomain) {
				category = rule["name"].(string)
				break
			}
		}
		categoryMap[category] = append(categoryMap[category], domain)
	}

	// 生成分组
	var groups []map[string]interface{}
	groupID := 1

	for category, domains := range categoryMap {
		// 计算该分类下的总URL数
		totalURLs := 0
		var sampleURLs []string
		urlSet := make(map[string]bool) // 用于去重

		for _, domain := range domains {
			urls := domainGroups[domain]
			totalURLs += len(urls)
		}

		// 收集所有URL并去重
		for _, domain := range domains {
			urls := domainGroups[domain]
			for _, url := range urls {
				if !urlSet[url.URL] {
					sampleURLs = append(sampleURLs, url.URL)
					urlSet[url.URL] = true
					// 限制示例URL数量
					if len(sampleURLs) >= 5 {
						break
					}
				}
			}
			if len(sampleURLs) >= 5 {
				break
			}
		}

		// 获取分类信息
		icon := "📁"
		color := "#6c757d"
		description := fmt.Sprintf("%s相关网站", category)

		// 查找匹配的规则
		for _, rule := range categoryRules {
			if rule["name"].(string) == category {
				icon = rule["icon"].(string)
				color = rule["color"].(string)
				description = rule["description"].(string)
				break
			}
		}

		// 计算置信度（基于访问频率）
		confidence := 0.7
		if totalURLs > 5 {
			confidence = 0.9
		} else if totalURLs > 2 {
			confidence = 0.8
		}

		group := map[string]interface{}{
			"id":          fmt.Sprintf("test_group_%d", groupID),
			"name":        category,
			"description": description,
			"icon":        icon,
			"color":       color,
			"urlCount":    totalURLs,
			"confidence":  confidence,
			"sampleURLs":  sampleURLs,
			"domains":     domains,
		}
		groups = append(groups, group)
		groupID++
	}

	// 按URL数量排序
	sort.Slice(groups, func(i, j int) bool {
		iCount, _ := groups[i]["urlCount"].(int)
		jCount, _ := groups[j]["urlCount"].(int)
		return iCount > jCount
	})

	return groups
}

// deduplicateURLs URL去重处理，只保留域名和一级路径，去除动态参数
func deduplicateURLs(records []models.BrowsingRecord) []models.BrowsingRecord {
	// 用于存储去重后的URL
	urlMap := make(map[string]models.BrowsingRecord)

	for _, record := range records {
		// 标准化URL
		normalizedURL := normalizeURL(record.URL)
		if normalizedURL == "" {
			continue
		}

		// 如果这个标准化URL已经存在，合并访问次数
		if existingRecord, exists := urlMap[normalizedURL]; exists {
			existingRecord.VisitCount += record.VisitCount
			// 更新最后访问时间（取最新的）
			if record.LastVisit.After(existingRecord.LastVisit) {
				existingRecord.LastVisit = record.LastVisit
				existingRecord.LastVisitTime = record.LastVisitTime
			}
			// 更新标题（取最长的，通常更完整）
			if len(record.Title) > len(existingRecord.Title) {
				existingRecord.Title = record.Title
			}
			urlMap[normalizedURL] = existingRecord
		} else {
			// 创建新的记录
			newRecord := record
			newRecord.URL = normalizedURL
			// 重新提取域名和路径
			newRecord.Domain = extractDomainFromURL(normalizedURL)
			newRecord.Path = extractPathFromURL(normalizedURL)
			urlMap[normalizedURL] = newRecord
		}
	}

	// 转换为切片
	var result []models.BrowsingRecord
	for _, record := range urlMap {
		result = append(result, record)
	}

	return result
}

// normalizeURL 标准化URL，只保留域名和一级路径，去除动态参数
func normalizeURL(urlStr string) string {
	// 解析URL
	parsedURL, err := url.Parse(urlStr)
	if err != nil {
		return ""
	}

	// 只保留scheme、host和一级路径
	normalized := parsedURL.Scheme + "://" + parsedURL.Host

	// 处理路径，只保留一级路径
	if parsedURL.Path != "" && parsedURL.Path != "/" {
		pathParts := strings.Split(strings.Trim(parsedURL.Path, "/"), "/")
		if len(pathParts) > 0 && pathParts[0] != "" {
			normalized += "/" + pathParts[0]
		}
	}

	// 特殊处理：对于localhost和127.0.0.1，进一步标准化
	if strings.Contains(normalized, "localhost") || strings.Contains(normalized, "127.0.0.1") {
		// 对于本地开发环境，只保留域名和端口，不保留路径
		if strings.Contains(normalized, ":8080") {
			normalized = strings.Split(normalized, ":8080")[0] + ":8080"
		}
	}

	return normalized
}

// ExecuteAIGrouping 执行AI分组
func ExecuteAIGrouping(c *gin.Context) {
	var request struct {
		VersionID int `json:"versionId" binding:"required"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(http.StatusBadRequest, models.APIResponse{
			Code:    400,
			Message: "请求参数错误: " + err.Error(),
			Data:    nil,
		})
		return
	}

	// 获取版本信息
	version, err := database.GetAIGroupingVersion(fmt.Sprintf("%d", request.VersionID))
	if err != nil {
		c.JSON(http.StatusNotFound, models.APIResponse{
			Code:    404,
			Message: "版本未找到",
			Data:    nil,
		})
		return
	}

	// 获取浏览记录
	records, err := database.GetBrowsingRecordsFromDB()
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: "获取浏览记录失败: " + err.Error(),
			Data:    nil,
		})
		return
	}

	// 转换为URL特征
	features := convertRecordsToFeatures(records)

	// 创建分组管理器
	manager := algorithms.NewGroupingManager()

	// 执行分组
	groups, err := manager.GroupURLs(version.Config.AlgorithmType, features, version.Config)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.APIResponse{
			Code:    500,
			Message: "分组执行失败: " + err.Error(),
			Data:    nil,
		})
		return
	}

	// 保存分组到数据库
	for i, group := range groups {
		group.VersionID = fmt.Sprintf("%d", request.VersionID)
		group.Order = i + 1
		err := database.CreateAIGroup(&group)
		if err != nil {
			fmt.Printf("保存分组失败: %v\n", err)
		}

		// 保存URL分配
		for _, url := range group.URLs {
			assignment := &models.URLGroupAssignment{
				VersionID:  fmt.Sprintf("%d", request.VersionID),
				GroupID:    group.ID,
				URL:        url,
				Title:      extractTitleFromURL(url, records),
				Domain:     extractDomainFromURL(url),
				Path:       extractPathFromURL(url),
				VisitCount: getVisitCountFromURL(url, records),
				LastVisit:  getLastVisitFromURL(url, records),
				Confidence: group.Confidence,
				CreatedAt:  time.Now(),
			}
			err := database.CreateURLGroupAssignment(assignment)
			if err != nil {
				fmt.Printf("保存URL分配失败: %v\n", err)
			}
		}
	}

	// 更新版本状态
	version.Status = "completed"
	version.GroupedURLs = len(records)
	version.TotalURLs = len(records)
	now := time.Now()
	version.CompletedAt = &now
	err = database.UpdateAIGroupingVersion(version)
	if err != nil {
		fmt.Printf("更新版本状态失败: %v\n", err)
	}

	c.JSON(http.StatusOK, models.APIResponse{
		Code:    200,
		Message: "分组执行完成",
		Data: map[string]interface{}{
			"groups":      groups,
			"totalGroups": len(groups),
			"totalURLs":   len(records),
		},
	})
}

// convertRecordsToFeatures 将浏览记录转换为URL特征
func convertRecordsToFeatures(records []models.BrowsingRecord) []models.URLFeature {
	// 按URL聚合记录
	urlMap := make(map[string]*models.URLFeature)

	for _, record := range records {
		if feature, exists := urlMap[record.URL]; exists {
			feature.VisitCount++
			if record.LastVisit.After(feature.LastVisit) {
				feature.LastVisit = record.LastVisit
			}
		} else {
			urlMap[record.URL] = &models.URLFeature{
				URL:        record.URL,
				Title:      record.Title,
				Domain:     record.Domain,
				Path:       record.Path,
				VisitCount: 1,
				FirstVisit: record.FirstVisit,
				LastVisit:  record.LastVisit,
				Keywords:   extractKeywordsFromURL(record.URL, record.Title),
				Category:   inferCategoryFromURL(record.URL, record.Title),
			}
		}
	}

	// 转换为切片
	var features []models.URLFeature
	for _, feature := range urlMap {
		features = append(features, *feature)
	}

	return features
}

// extractTitleFromURL 从URL提取标题
func extractTitleFromURL(url string, records []models.BrowsingRecord) string {
	for _, record := range records {
		if record.URL == url {
			return record.Title
		}
	}
	return ""
}

// extractDomainFromURL 从URL提取域名
func extractDomainFromURL(url string) string {
	parts := strings.Split(url, "/")
	if len(parts) >= 3 {
		return strings.TrimPrefix(parts[2], "www.")
	}
	return ""
}

// extractPathFromURL 从URL提取路径
func extractPathFromURL(url string) string {
	parts := strings.Split(url, "/")
	if len(parts) >= 4 {
		return "/" + strings.Join(parts[3:], "/")
	}
	return "/"
}

// getVisitCountFromURL 获取URL访问次数
func getVisitCountFromURL(url string, records []models.BrowsingRecord) int {
	count := 0
	for _, record := range records {
		if record.URL == url {
			count++
		}
	}
	return count
}

// getLastVisitFromURL 获取URL最后访问时间
func getLastVisitFromURL(url string, records []models.BrowsingRecord) time.Time {
	var lastVisit time.Time
	for _, record := range records {
		if record.URL == url && record.LastVisit.After(lastVisit) {
			lastVisit = record.LastVisit
		}
	}
	return lastVisit
}

// extractKeywordsFromURL 从URL和标题提取关键词
func extractKeywordsFromURL(url, title string) []string {
	var keywords []string

	// 从域名提取关键词
	domain := extractDomainFromURL(url)
	parts := strings.Split(domain, ".")
	if len(parts) > 0 {
		keywords = append(keywords, parts[0])
	}

	// 从标题提取关键词
	titleWords := strings.Fields(strings.ToLower(title))
	for _, word := range titleWords {
		if len(word) > 2 {
			keywords = append(keywords, word)
		}
	}

	return keywords
}

// inferCategoryFromURL 从URL推断类别
func inferCategoryFromURL(url, title string) string {
	urlLower := strings.ToLower(url)
	titleLower := strings.ToLower(title)

	// 技术相关
	if strings.Contains(urlLower, "github") || strings.Contains(urlLower, "stackoverflow") ||
		strings.Contains(urlLower, "developer") || strings.Contains(titleLower, "编程") {
		return "技术开发"
	}

	// 学习相关
	if strings.Contains(urlLower, "coursera") || strings.Contains(urlLower, "udemy") ||
		strings.Contains(urlLower, "zhihu") || strings.Contains(titleLower, "学习") {
		return "学习资源"
	}

	// 娱乐相关
	if strings.Contains(urlLower, "youtube") || strings.Contains(urlLower, "bilibili") ||
		strings.Contains(urlLower, "netflix") || strings.Contains(titleLower, "娱乐") {
		return "娱乐休闲"
	}

	// 工作相关
	if strings.Contains(urlLower, "linkedin") || strings.Contains(urlLower, "indeed") ||
		strings.Contains(titleLower, "工作") || strings.Contains(titleLower, "职业") {
		return "职业发展"
	}

	// 购物相关
	if strings.Contains(urlLower, "amazon") || strings.Contains(urlLower, "taobao") ||
		strings.Contains(urlLower, "jd") || strings.Contains(titleLower, "购物") {
		return "购物消费"
	}

	return "其他"
}

// createGroupsFromTestResult 使用测试结果创建分组
func createGroupsFromTestResult(versionID int, testResult map[string]interface{}) error {
	groups, ok := testResult["groups"].([]interface{})
	if !ok {
		return fmt.Errorf("测试结果中没有分组数据")
	}

	var totalURLs int
	var groupedURLs int

	for _, groupData := range groups {
		group, ok := groupData.(map[string]interface{})
		if !ok {
			continue
		}

		// 创建分组
		aiGroup := models.AIGroup{
			VersionID:   strconv.Itoa(versionID),
			Name:        getStringValue(group, "name"),
			Description: getStringValue(group, "description"),
			Color:       getStringValue(group, "color"),
			Icon:        getStringValue(group, "icon"),
			Confidence:  getFloatValue(group, "confidence"),
		}

		err := database.CreateAIGroup(&aiGroup)
		if err != nil {
			return fmt.Errorf("创建分组失败: %v", err)
		}

		groupID := aiGroup.ID

		// 获取分组的URL列表
		sampleURLs, ok := group["sampleURLs"].([]interface{})
		if !ok {
			continue
		}

		// 为每个URL创建分配记录
		for _, urlData := range sampleURLs {
			url, ok := urlData.(string)
			if !ok {
				continue
			}

			// 从URL提取域名和路径
			domain := extractDomainFromURL(url)
			path := extractPathFromURL(url)

			// 创建URL分配记录
			assignment := models.URLGroupAssignment{
				GroupID:    groupID,
				VersionID:  strconv.Itoa(versionID),
				URL:        url,
				Title:      generateTitleFromURL(url),
				Domain:     domain,
				Path:       path,
				VisitCount: 1,
				LastVisit:  time.Now(),
				Confidence: getFloatValue(group, "confidence"),
			}

			err := database.CreateURLGroupAssignment(&assignment)
			if err != nil {
				// 记录错误但继续处理其他URL
				fmt.Printf("创建URL分配失败: %v\n", err)
			} else {
				groupedURLs++
			}
			totalURLs++
		}
	}

	// 更新版本统计信息
	err := database.UpdateAIGroupingVersionStats(strconv.Itoa(versionID), totalURLs, groupedURLs)
	if err != nil {
		fmt.Printf("更新版本统计信息失败: %v\n", err)
		// 不返回错误，因为分组已经创建成功
	}

	return nil
}

// getStringValue 从map中安全获取字符串值
func getStringValue(data map[string]interface{}, key string) string {
	if value, ok := data[key]; ok {
		if str, ok := value.(string); ok {
			return str
		}
	}
	return ""
}

// getFloatValue 从map中安全获取浮点数值
func getFloatValue(data map[string]interface{}, key string) float64 {
	if value, ok := data[key]; ok {
		if f, ok := value.(float64); ok {
			return f
		}
	}
	return 0.0
}

// generateTitleFromURL 从URL生成标题
func generateTitleFromURL(urlStr string) string {
	// 解析URL
	parsedURL, err := url.Parse(urlStr)
	if err != nil {
		return "网站链接"
	}

	domain := parsedURL.Host
	if domain == "" {
		return "网站链接"
	}

	// 移除www前缀
	domain = strings.TrimPrefix(domain, "www.")

	// 根据域名生成标题
	if strings.Contains(domain, "github.com") {
		return "GitHub - 代码托管平台"
	} else if strings.Contains(domain, "stackoverflow.com") {
		return "Stack Overflow - 编程问答社区"
	} else if strings.Contains(domain, "baidu.com") {
		return "百度 - 搜索引擎"
	} else if strings.Contains(domain, "localhost") || strings.Contains(domain, "127.0.0.1") {
		return "本地开发环境"
	} else if strings.Contains(domain, "weibo.com") {
		return "微博 - 社交媒体"
	} else if strings.Contains(domain, "taobao.com") {
		return "淘宝 - 电商平台"
	} else if strings.Contains(domain, "jd.com") {
		return "京东 - 电商平台"
	} else if strings.Contains(domain, "amazon.com") {
		return "亚马逊 - 电商平台"
	} else if strings.Contains(domain, "twitter.com") {
		return "Twitter - 社交媒体"
	} else if strings.Contains(domain, "facebook.com") {
		return "Facebook - 社交网络"
	} else if strings.Contains(domain, "instagram.com") {
		return "Instagram - 图片社交"
	} else if strings.Contains(domain, "reddit.com") {
		return "Reddit - 社区论坛"
	} else if strings.Contains(domain, "cnn.com") {
		return "CNN - 国际新闻"
	} else if strings.Contains(domain, "bbc.com") {
		return "BBC - 国际新闻"
	} else if strings.Contains(domain, "ctrip.com") {
		return "携程 - 旅游服务"
	} else if strings.Contains(domain, "npmjs.com") {
		return "npm - 包管理器"
	} else if strings.Contains(domain, "kubernetes.io") {
		return "Kubernetes - 容器编排"
	} else if strings.Contains(domain, "docker.com") {
		return "Docker - 容器技术"
	} else if strings.Contains(domain, "ycombinator.com") {
		return "Hacker News - 技术新闻"
	} else if strings.Contains(domain, "hao123.com") {
		return "hao123 - 网址导航"
	} else if strings.Contains(domain, "sohu.com") {
		return "搜狐 - 新闻门户"
	} else if strings.Contains(domain, "sina.com.cn") {
		return "新浪 - 新闻门户"
	} else if strings.Contains(domain, "qq.com") {
		return "腾讯 - 综合门户"
	} else if strings.Contains(domain, "163.com") {
		return "网易 - 新闻门户"
	} else if strings.Contains(domain, "publicservices.hrss.tj.gov.cn") {
		return "天津人社 - 政府服务"
	} else {
		// 默认生成标题
		domainParts := strings.Split(domain, ".")
		if len(domainParts) > 0 {
			siteName := strings.Title(domainParts[0])
			return siteName + " - 网站"
		}
		return "网站链接"
	}
}

// UseGrouping 使用指定的分组版本
func UseGrouping(c *gin.Context) {
	var request struct {
		VersionID  interface{}            `json:"versionId" binding:"required"`
		TestResult map[string]interface{} `json:"testResult,omitempty"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(400, gin.H{
			"code":    400,
			"message": "请求参数错误: " + err.Error(),
		})
		return
	}

	// 处理versionId，支持字符串和数字类型
	var versionID int
	var err error

	switch v := request.VersionID.(type) {
	case string:
		versionID, err = strconv.Atoi(v)
	case float64:
		versionID = int(v)
	case int:
		versionID = v
	default:
		c.JSON(400, gin.H{
			"code":    400,
			"message": "版本ID格式错误: 必须是字符串或数字类型",
		})
		return
	}

	if err != nil {
		c.JSON(400, gin.H{
			"code":    400,
			"message": "版本ID格式错误: " + err.Error(),
		})
		return
	}

	// 如果提供了测试结果，直接使用测试结果创建分组
	if request.TestResult != nil {
		err := createGroupsFromTestResult(versionID, request.TestResult)
		if err != nil {
			c.JSON(500, gin.H{
				"code":    500,
				"message": "使用测试结果创建分组失败: " + err.Error(),
			})
			return
		}

		// 更新版本状态为已完成
		err = database.UpdateAIGroupingVersionStatus(strconv.Itoa(versionID), "completed")
		if err != nil {
			c.JSON(500, gin.H{
				"code":    500,
				"message": "更新版本状态失败: " + err.Error(),
			})
			return
		}

		c.JSON(200, gin.H{
			"code":    200,
			"message": "成功使用测试结果创建分组",
			"data":    map[string]interface{}{"versionId": versionID},
		})
		return
	}

	// 检查版本是否存在且已完成
	version, err := database.GetAIGroupingVersion(strconv.Itoa(versionID))
	if err != nil {
		c.JSON(404, gin.H{
			"code":    404,
			"message": "分组版本不存在",
		})
		return
	}

	if version.Status != "completed" {
		c.JSON(400, gin.H{
			"code":    400,
			"message": "分组版本尚未完成，无法使用",
		})
		return
	}

	// 获取该版本的所有分组
	groups, err := database.GetAIGroupsByVersionID(versionID)
	if err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "获取分组失败: " + err.Error(),
		})
		return
	}

	// 获取每个分组的URL分配
	var groupedURLs []map[string]interface{}
	for _, group := range groups {
		groupID, _ := strconv.Atoi(group.ID)
		assignments, err := database.GetURLGroupAssignmentsByGroupID(groupID)
		if err != nil {
			continue
		}

		var urls []map[string]interface{}
		for _, assignment := range assignments {
			urls = append(urls, map[string]interface{}{
				"url":        assignment.URL,
				"title":      assignment.Title,
				"domain":     assignment.Domain,
				"path":       assignment.Path,
				"visitCount": assignment.VisitCount,
				"lastVisit":  assignment.LastVisit,
				"confidence": assignment.Confidence,
			})
		}

		groupedURLs = append(groupedURLs, map[string]interface{}{
			"group": map[string]interface{}{
				"id":          group.ID,
				"name":        group.Name,
				"description": group.Description,
				"color":       group.Color,
				"icon":        group.Icon,
			},
			"urls": urls,
		})
	}

	// 将分组数据保存到配置中，供个人导航页面使用
	// 这里可以将数据保存到数据库或配置文件中
	// 为了简化，我们将其保存到内存中（实际项目中应该保存到数据库）

	// 更新版本状态为"使用中"
	version.Status = "active"
	err = database.UpdateAIGroupingVersion(version)
	if err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "更新版本状态失败: " + err.Error(),
		})
		return
	}

	c.JSON(200, gin.H{
		"code":    200,
		"message": "分组已成功应用到个人导航页面",
		"data": map[string]interface{}{
			"versionId":   request.VersionID,
			"versionName": version.Name,
			"groupCount":  len(groups),
			"totalURLs":   len(groupedURLs),
		},
	})
}

// GetActiveGrouping 获取当前使用的分组数据
func GetActiveGrouping(c *gin.Context) {
	// 查找状态为"active"的分组版本
	versions, err := database.GetAllAIGroupingVersions()
	if err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "获取分组版本失败: " + err.Error(),
		})
		return
	}

	var activeVersion *models.AIGroupingVersion
	for _, version := range versions {
		if version.Status == "active" {
			activeVersion = &version
			break
		}
	}

	if activeVersion == nil {
		c.JSON(404, gin.H{
			"code":    404,
			"message": "没有正在使用的分组版本",
		})
		return
	}

	// 获取该版本的所有分组
	versionID, _ := strconv.Atoi(activeVersion.ID)
	groups, err := database.GetAIGroupsByVersionID(versionID)
	if err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "获取分组失败: " + err.Error(),
		})
		return
	}

	// 获取每个分组的URL分配
	var groupedData []map[string]interface{}
	for _, group := range groups {
		groupID, _ := strconv.Atoi(group.ID)
		assignments, err := database.GetURLGroupAssignmentsByGroupID(groupID)
		if err != nil {
			continue
		}

		var urls []map[string]interface{}
		for _, assignment := range assignments {
			urls = append(urls, map[string]interface{}{
				"url":        assignment.URL,
				"title":      assignment.Title,
				"domain":     assignment.Domain,
				"path":       assignment.Path,
				"visitCount": assignment.VisitCount,
				"lastVisit":  assignment.LastVisit,
				"confidence": assignment.Confidence,
			})
		}

		groupedData = append(groupedData, map[string]interface{}{
			"group": map[string]interface{}{
				"id":          group.ID,
				"name":        group.Name,
				"description": group.Description,
				"color":       group.Color,
				"icon":        group.Icon,
			},
			"urls": urls,
		})
	}

	c.JSON(200, gin.H{
		"code":    200,
		"message": "success",
		"data": map[string]interface{}{
			"version": activeVersion,
			"groups":  groupedData,
		},
	})
}

// DownloadHandler 下载页面处理器
func DownloadHandler(c *gin.Context) {
	c.HTML(200, "download.html", gin.H{})
}

// DownloadFile 下载文件处理器
func DownloadFile(c *gin.Context) {
	platform := c.Param("platform")

	// 定义平台对应的文件路径
	fileMap := map[string]string{
		"macos-arm64":   "exe/navigation-service-macos-arm64",
		"windows-amd64": "exe/navigation-service-windows-amd64.exe",
		"windows-arm64": "exe/navigation-service-windows-arm64.exe",
		"linux-amd64":   "exe/navigation-service-linux-amd64",
		"linux-arm64":   "exe/navigation-service-linux-arm64",
	}

	// 检查平台是否支持
	filePath, exists := fileMap[platform]
	if !exists {
		c.JSON(404, gin.H{
			"code":    404,
			"message": "不支持的平台: " + platform,
		})
		return
	}

	// 检查文件是否存在
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		c.JSON(404, gin.H{
			"code":    404,
			"message": "文件不存在: " + filePath,
		})
		return
	}

	// 设置下载文件名
	var fileName string
	switch platform {
	case "macos-arm64":
		fileName = "NavigationService-macos-arm64"
	case "windows-amd64":
		fileName = "navigation-service-windows-amd64.exe"
	case "windows-arm64":
		fileName = "navigation-service-windows-arm64.exe"
	case "linux-amd64":
		fileName = "navigation-service-linux-amd64"
	case "linux-arm64":
		fileName = "navigation-service-linux-arm64"
	default:
		fileName = "navigation-service-" + platform
	}

	// 设置响应头
	c.Header("Content-Description", "File Transfer")
	c.Header("Content-Transfer-Encoding", "binary")
	c.Header("Content-Disposition", "attachment; filename="+fileName)
	c.Header("Content-Type", "application/octet-stream")

	// 发送文件
	c.File(filePath)
}

// CheckDownloadFile 检查下载文件是否存在
func CheckDownloadFile(c *gin.Context) {
	platform := c.Param("platform")

	// 定义平台对应的文件路径
	fileMap := map[string]string{
		"macos-arm64":   "exe/navigation-service-macos-arm64",
		"windows-amd64": "exe/navigation-service-windows-amd64.exe",
		"windows-arm64": "exe/navigation-service-windows-arm64.exe",
		"linux-amd64":   "exe/navigation-service-linux-amd64",
		"linux-arm64":   "exe/navigation-service-linux-arm64",
	}

	// 检查平台是否支持
	filePath, exists := fileMap[platform]
	if !exists {
		c.JSON(200, gin.H{
			"available": false,
			"message":   "不支持的平台: " + platform,
		})
		return
	}

	// 检查文件是否存在
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		c.JSON(200, gin.H{
			"available": false,
			"message":   "文件不存在: " + filePath,
		})
		return
	}

	// 获取文件信息
	fileInfo, err := os.Stat(filePath)
	if err != nil {
		c.JSON(200, gin.H{
			"available": false,
			"message":   "无法获取文件信息: " + err.Error(),
		})
		return
	}

	c.JSON(200, gin.H{
		"available": true,
		"message":   "文件可用",
		"size":      fileInfo.Size(),
		"modified":  fileInfo.ModTime(),
	})
}
